package com.lhkj.ct.base.utils;

import cn.hutool.core.collection.CollectionUtil;
import com.lhkj.ct.base.model.IBaseTree;
import com.lhkj.ct.base.model.Option;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 *     下拉选项构建类
 * </p>
 */
public class OptionUtil {

    public static <T, V> List<Option<V>> buildOption(List<T> data, Function<T, V> value, Function<T, String> label) {
        List<Option<V>> list = new ArrayList<>();
        for (T t : data) {
            Option<V> option = new Option<>(value.apply(t), label.apply(t));
            list.add(option);
        }
        return list;
    }
    
    public static <T extends IBaseTree<V>, V> List<Option<V>> buildTreeOption(List<T> data, Function<T, String> label) {
        Set<V> parentIds = data.stream()
                .map(T::getParentId)
                .collect(Collectors.toSet());

        Set<V> deptIds = data.stream()
                .map(T::getId)
                .collect(Collectors.toSet());

        List<V> rootIds = CollectionUtil.subtractToList(parentIds, deptIds);

        List<Option<V>> list = new ArrayList<>();
        for (V rootId : rootIds) {
            list.addAll(recurDeptTreeOptions(rootId, data, label));
        }
        return list;
    }

    /**
     * 递归生成部门表格层级列表
     *
     * @param parentId
     * @param deptList
     * @return
     */
    private static <T extends IBaseTree<V>, V> List<Option<V>> recurDeptTreeOptions(V parentId, List<T> deptList, Function<T, String> label) {
        List<Option<V>> list = CollectionUtil.emptyIfNull(deptList).stream()
                .filter(dept -> dept.getParentId().equals(parentId))
                .map(dept -> {
                    Option<V> option = new Option<>(dept.getId(), label.apply(dept));
                    List<Option<V>> children = recurDeptTreeOptions(dept.getId(), deptList, label);
                    if (CollectionUtil.isNotEmpty(children)) {
                        option.setChildren(children);
                    }
                    return option;
                })
                .collect(Collectors.toList());
        return list;
    }
}
